﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Input.Touch;
using Microsoft.Xna.Framework.GamerServices;

namespace PhysicsSimulator
{
    public partial class TurnablePage : PhoneApplicationPage
    {
        ContentManager contentManager;
        GameTimer timer;
        SpriteBatch spriteBatch;

        UIElementRenderer elementRenderer;

        CTurnable _turnable = null;
        CTurnableStop _turnableStop = null;
        List<CTurnableObject> _turnableObjects = new List<CTurnableObject>();

        int _touchID = -1;
        Vector2 _lastTouchPoint = Vector2.Zero;
        Vector2 _currentTouchPoint = Vector2.Zero;

        bool _isLoaded = false;

        bool _is_playing = false;

        public TurnablePage()
        {
            InitializeComponent();

            contentManager = (Application.Current as App).Content;

            timer = new GameTimer();
            timer.UpdateInterval = TimeSpan.FromTicks(333333);
            timer.Update += timer_Update;
            timer.Draw += timer_Draw;

            LayoutUpdated += TurnablePage_LayoutUpdated;
        }

        CVectorForce v, a;

        public enum ButtonTypes
        {   
            Save = 0,         
            Play_Pause = 1,
            Refresh = 2
        }
        public ApplicationBarIconButton GetButton(ButtonTypes whichButton)
        {
            return ApplicationBar.Buttons[(int)whichButton]
               as ApplicationBarIconButton;
        }

        void TurnablePage_LayoutUpdated(object sender, EventArgs e)
        {
            if (ActualWidth == 0 || ActualHeight == 0)
                return;

            // see if we already have the right sized renderer
            if (elementRenderer != null &&
                elementRenderer.Texture != null &&
                elementRenderer.Texture.Width == (int)ActualWidth &&
                elementRenderer.Texture.Height == (int)ActualHeight)
            {
                return;
            }

            // dispose the current renderer
            if (elementRenderer != null)
                elementRenderer.Dispose();

            // create the renderer
            elementRenderer = new UIElementRenderer(LayoutRoot, (int)ActualWidth, (int)ActualHeight);
        }

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            SharedGraphicsDeviceManager.Current.GraphicsDevice.SetSharingMode(true);

            spriteBatch = new SpriteBatch(SharedGraphicsDeviceManager.Current.GraphicsDevice);

            if (!_isLoaded)
            {
                _isLoaded = true;
                _turnable = new CTurnable(spriteBatch);
                _turnable.Init(contentManager);
                _turnable.Position = new Vector2(240, 240);

                _turnableStop = new CTurnableStop(spriteBatch);
                _turnableStop.Init(contentManager);
                _turnableStop.SetLimited(_turnable.Position + new Vector2(155, 155), _turnable.Position + new Vector2(147.5f, 147.5f));
                _turnableStop.Stop += _turnableStop_Stop;
                for (int i = 0; i < 5; i++)
                {
                    CTurnableObject to = new CTurnableObject(spriteBatch, i + 1, new CSprite(contentManager.Load<Texture2D>("Images/Turnable/ball-" + i.ToString())));
                    to.Init(contentManager);
                    to.IdlePosition = new Vector2(48 + 96 * i, 650);
                    _turnableObjects.Add(to);
                }
            }
            else
            {
                _turnable.SpriteBatch = spriteBatch;
                _turnableStop.SpriteBatch = spriteBatch;
                foreach (CTurnableObject _turnableObject in _turnableObjects)
                {
                    _turnableObject.SpriteBatch = spriteBatch;
                }
            }

            _turnable.AngleVelocity = Settings.TurnableVelocity;

            a = new CVectorForce(spriteBatch);
            a.Init(contentManager);
            a.Create(new Vector2(65,67), new Vector2(100,100), 2, Color.HotPink);
            a.VectorForce = new Vector2(35, 0);
            v = new CVectorForce(spriteBatch);
            v.Init(contentManager);
            v.Create(new Vector2(65,35), new Vector2(100,50), 2, Color.Green);
            v.VectorForce = new Vector2(35, 0);

            if (Settings.moment_save_active)
            {
                GetButton(ButtonTypes.Save).IsEnabled = true;
            }
            else
            {
                GetButton(ButtonTypes.Save).IsEnabled = false;
            }

            timer.Start();
        }

        void _turnableStop_Stop(object sender, EventArgs e)
        {
            if (_turnable.AngleVelocity > 0)
            {
                _turnable.AngleVelocity = _turnable.AngleVelocity * 0.975f - 0.01f;
                if (_turnable.AngleVelocity < 0)
                    _turnable.AngleVelocity = 0;
            }
        }

        protected override void OnNavigatedFrom(NavigationEventArgs e)
        {
            timer.Stop();
            SharedGraphicsDeviceManager.Current.GraphicsDevice.SetSharingMode(false);
            base.OnNavigatedFrom(e);
        }

        void timer_Update(object sender, GameTimerEventArgs e)
        {

            if (_is_playing)
                return;

            AngleVelocityTXB.Text = _turnable.AngleVelocity.ToString();
            WdTXB.Text = _turnable.Power.ToString();

            TouchCollection touches = TouchPanel.GetState();
            foreach (TouchLocation tl in touches)
            {
                switch (tl.State)
                {
                    case TouchLocationState.Pressed:
                        bool object_handled = false;
                        foreach (CTurnableObject _turnableObject in _turnableObjects)
                        {
                            _turnableObject.Pressed(tl);
                            if (_turnableObject.CurrentState == TurnableObjectState.DRAG)
                                object_handled = true;
                        }
                        if (_turnable.IsPointInside(tl.Position) && !object_handled)
                        {
                            _touchID = tl.Id;
                            _lastTouchPoint = _currentTouchPoint = tl.Position;
                            _turnable.AngleVelocity = 0;
                        }
                        _turnableStop.HandleTouch(tl.Position);
                        foreach (CTurnableObject _turnableObject in _turnableObjects)
                        {
                            _turnableObject.Pressed(tl);
                            if (_turnableObject.CheckRemoveEx(tl))
                            {
                                _turnable.RemoveObject(_turnableObject);
                                _turnableObject.SetIdleState();
                            }
                        }
                        break;
                    case TouchLocationState.Moved:
                        if (tl.Id == _touchID)
                        {
                            _lastTouchPoint = _currentTouchPoint;
                            _currentTouchPoint = tl.Position;
                            _turnable.UpdateDragState(_lastTouchPoint, _currentTouchPoint);
                        }
                        foreach (CTurnableObject _turnableObject in _turnableObjects)
                        {
                            _turnableObject.Move(tl);
                        }
                        break;
                    case TouchLocationState.Released:
                        if (tl.Id == _touchID)
                        {
                            _turnable.ReleaseDrag(_lastTouchPoint, _currentTouchPoint);
                            _touchID = -1;
                        }
                        _turnableStop.ReleasePressed();
                        foreach (CTurnableObject _turnableObject in _turnableObjects)
                        {
                            if (_turnableObject.Release(tl))
                                _turnable.CheckPlusObject(_turnableObject);
                        }
                        break;
                }
            }
            _turnable.Update(e);
            _turnableStop.Update(e);
            foreach (CTurnableObject _turnableObject in _turnableObjects)
            {
                _turnableObject.Update(e);
            }

            if (Settings.TurnableEnviromentRatio > 0)
            {
                if (_turnable.AngleVelocity > 0)
                {
                    _turnable.AngleVelocity = _turnable.AngleVelocity - Settings.TurnableEnviromentRatio * 0.005f;
                    if (_turnable.AngleVelocity < 0)
                        _turnable.AngleVelocity = 0;
                }
            }
        }

        void timer_Draw(object sender, GameTimerEventArgs e)
        {
            SharedGraphicsDeviceManager.Current.GraphicsDevice.Clear(Color.CornflowerBlue);

            elementRenderer.Render();

            spriteBatch.Begin();
            _turnable.Draw(e);
            _turnableStop.Draw(e);
            foreach (CTurnableObject _turnableObject in _turnableObjects)
            {
                _turnableObject.Draw(e);
            }
            spriteBatch.Draw(elementRenderer.Texture, Vector2.Zero, Microsoft.Xna.Framework.Color.White);

            spriteBatch.End();
            a.Draw(e);
            v.Draw(e);
        }

        private void ApplicationBarMenuItem_Click(object sender, EventArgs e)
        {
            Settings.RenewTempData();
            NavigationService.Navigate(new Uri("/Moments/TurnableInputDataPage.xaml", UriKind.Relative));
        }

        private void ApplicationBarMenuItem_Click_1(object sender, EventArgs e)
        {
            NavigationService.Navigate(new Uri("/Moments/TurnableInfoPage.xaml", UriKind.Relative));
        }

        private void _play_Click(object sender, EventArgs e)
        {
            if (!_is_playing && _turnable.AngleVelocity > 0)
            {
                GetButton(ButtonTypes.Play_Pause).IconUri = new Uri("/Assets/AppBar/appbar.transport.play.rest.png", UriKind.Relative);
                GetButton(ButtonTypes.Play_Pause).Text = "pause";

                //GetButton(ButtonTypes.Refresh).IsEnabled = false;
                _is_playing = true;
            }
            else
            {
                GetButton(ButtonTypes.Play_Pause).IconUri = new Uri("/Assets/AppBar/appbar.transport.pause.rest.png", UriKind.Relative);
                GetButton(ButtonTypes.Play_Pause).Text = "play";

                //GetButton(ButtonTypes.Refresh).IsEnabled = true;
                _is_playing = false;
            }
        }

        private void _refresh_Click(object sender, EventArgs e)
        {
            _is_playing = false;
            _turnable.Reset();
        }

        private void ApplicationBarMenuItem_Click_2(object sender, System.EventArgs e)
        {
            NavigationService.Navigate(new Uri("/Moments/SaveMomentPage.xaml", UriKind.Relative));
        }

        private void _save_Click(object sender, System.EventArgs e)
        {
            if (!Guide.IsVisible)
            {
                // display the guide

                Guide.BeginShowKeyboardInput(PlayerIndex.One,
                    "Tên",       // title for the page
                    "Nhập tên mô phỏng",  // question for user
                    null,             // default text
                    new AsyncCallback(GotTextName),  // callback method 
                    this);                       // object reference
            }


        }
        void GotTextName(IAsyncResult result)
        {
            if (result.IsCompleted)
            {
                List<MomentData> datas = MomentData.Load();

                string text = Guide.EndShowKeyboardInput(result);

                if (text != null)
                {
                    if (text == "")
                    {
                        text = "unknown";
                    }
                    Settings.moment_save_active = false;
                    MomentData data = new MomentData(text, Settings.TurnableVelocity, Settings.TurnableWeight, Settings.TurnableRadial, Settings.TurnableEnviromentRatio);
                    datas.Add(data);
                    MomentData.SaveData(datas);
                }
            }
        }
    }
}